////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2016-2018 Qualcomm Technologies, Inc.
// All Rights Reserved.
// Confidential and Proprietary - Qualcomm Technologies, Inc.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @file  camxifenode.h
/// @brief IFENode class declarations
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef CAMXIFENODE_H
#define CAMXIFENODE_H

#include "camxcmdbuffermanager.h"
#include "camxcslifedefs.h"
#include "camxcslispdefs.h"
#include "camxhwcontext.h"
#include "camxispiqmodule.h"
#include "camxispstatsmodule.h"
#include "camxmem.h"
#include "camxnode.h"
#include "camxpropertyblob.h"
#include "camxstatsdebugdatawriter.h"
#include "camxtitan17xcontext.h"

CAMX_NAMESPACE_BEGIN

class DualIFEUtils;

static const UINT IFEMetadataOutputTags[] =
{
    PropertyIDIFEDigitalZoom,
    PropertyIDIFEAppliedCrop,
    PropertyIDIFEGammaOutput,
    PropertyIDISPBFConfig,
    PropertyIDISPIHistConfig,
    PropertyIDISPAWBBGConfig,
    PropertyIDISPHDRBEConfig,
    PropertyIDISPBHistConfig,
    PropertyIDISPHDRBHistConfig,
    PropertyIDIFEScaleOutput,
    PropertyIDISPTintlessBGConfig,
    PropertyIDISPRSConfig,
    PropertyIDISPCSConfig,
    PropertyIDIFEADRCInfoOutput,
    ScalerCropRegion,
    ShadingMode,
    StatisticsLensShadingMapMode,
    LensInfoShadingMapSize,
    StatisticsLensShadingMap,
    SensorDynamicBlackLevel,
    SensorDynamicWhiteLevel,
    SensorBlackLevelPattern,
    SensorNeutralColorPoint,
    BlackLevelLock,
    ColorCorrectionGains,
    ControlPostRawSensitivityBoost,
    HotPixelMode,
    NoiseReductionMode,
    StatisticsHotPixelMapMode,
    TonemapMode,
};

static const UINT NumIFEMetadataOutputTags = sizeof(IFEMetadataOutputTags) / sizeof(UINT32);   ///< Number of output vendor tags

static const UINT IFEMetadataRawOutputTags[] =
{
    SensorNeutralColorPoint,
};

static const UINT NumIFEMetadataRawOutputTags = sizeof(IFEMetadataRawOutputTags) / sizeof(UINT32);

/// @brief List of framework tags
static UINT32 IFEMetadataTags[] =
{
    InputBlackLevelLock                  ,
    InputColorCorrectionGains            ,
    InputColorCorrectionMode             ,
    InputColorCorrectionTransform        ,
    InputControlAEMode                   ,
    InputControlAWBMode                  ,
    InputControlMode                     ,
    InputControlPostRawSensitivityBoost  ,
    InputHotPixelMode                    ,
    InputNoiseReductionMode              ,
    InputShadingMode                     ,
    InputStatisticsHotPixelMapMode       ,
    InputStatisticsLensShadingMapMode    ,
    InputTonemapMode                     ,
    InputScalerCropRegion                ,
    InputControlAWBLock
};

static const UINT NumIFEMetadataTags = sizeof(IFEMetadataTags) / sizeof(UINT32);   ///< Number of vendor tags
// NOWHINE NC003a: Don't actually want this to be g_
static UINT64 IFEMetadataTagReqOffset[NumIFEMetadataTags] = { 0 };

/// @brief IFE Channel Type
enum class IFEChannelType
{
    PIXEL,       ///< Pixel Channel
    RDI,         ///< RDI   Channel
};

/// @brief IFE IQ Module Information
struct IFEIQModuleInfo
{
    ISPIQModuleType   moduleType;                                      ///< IQ Module Type
    IFEPipelinePath   IFEPath;                                         ///< IFE pipeline path
    BOOL              installed;                                       ///< Module Available or not
    CamxResult        (*IQCreate)(IFEModuleCreateData* pInputData);    ///< Static create fuction of this IQ Module
};

/// @brief IFE Stats Module Information
struct IFEStatsModuleInfo
{
    ISPStatsModuleType moduleType;                                              ///< Stats Module Name
    BOOL               installed;                                               ///< Module Available or not
    CamxResult         (*StatsCreate)(IFEStatsModuleCreateData* pInputData);    ///< Static create fuction of this Stats Module
};

/// @brief IFE Capability Information
struct IFECapabilityInfo
{
    UINT                numIFEIQModule;            ///< Number of IQ Modules
    IFEIQModuleInfo*    pIFEIQModuleList;          ///< List of IQ Module
    UINT                numIFEStatsModule;         ///< Number of Stats Modules
    IFEStatsModuleInfo* pIFEStatsModuleList;       ///< List of Stats Module
    UINT                numRDILinkPerIFE;          ///< Number of RDI Link per IFE
    UINT                numIFE;                    ///< Number of IFE
};

/// @brief CAMIF Pixel extraction data
struct IFECAMIFPixelExtractionData
{
    UINT32 xCordrinate;      ///< X Coordinate of Pixel
    UINT32 yCordrinate;      ///< Y cooridnate of Pixel
    UINT32 flag;             ///< 0 - Left, 1 - Right
    UINT32 blockX;           ///< block Index
    UINT32 blockY;           ///< block Index
};

struct IFEStripingInput;

CAMX_BEGIN_PACKED

/// @brief Dual IFE split params
struct DualIFESplitParams
{
    UINT32  splitPoint;     ///< x, where (0 < x < width) and left IFE's input ends at x + rightPadding and
                            ///  right IFE's input starts at x - leftPadding (in pixel)
    UINT32  rightPadding;   ///< The padding added past the split point for left IFE's input (in pixel)
    UINT32  leftPadding;    ///< The padding added before the split point for right IFE's input (in pixel)
    UINT32  reserved;       ///< Reserved
} CAMX_PACKED;

/// @brief IFE stripe info per bus client
struct IFEStripeConfig
{
    UINT32  offset;     ///< Start horizontal offset relative to output buffer (in byte)
                        ///  In UBWC mode, this will indicate the H_INIT value (in pixel)
    UINT32  width;      ///< Width of the stripe (in bytes)
    UINT32  tileConfig; ///< UBWC meta tile config (contains partial tile info)
    UINT32  portId;     ///< Reserved
}  CAMX_PACKED;

static const UINT32 CSLMaxNumIFEStripes = 2;    ///< Dual IFE hence 2

/// @brief Dual IFE configuration
struct IFEDualConfig
{
    UINT32              numPorts;       ///< Max number of ports
    UINT32              reserved;       ///< Reserverd
    DualIFESplitParams  splitParams;    ///< Input split
    IFEStripeConfig     stripes[1];     ///< Stripe information: stripes[CSLMaxNumIFEStripes][numPorts][CSLMaxNumPlanes]
} CAMX_PACKED;

static const UINT32 MaxStripeConfigSize =
    sizeof(IFEDualConfig) + (sizeof(IFEStripeConfig) * ((2 * CSLIFEPortIdMaxNumPortResources * CSLMaxNumPlanes) - 1));

/// @brief HFR configuration for a Port
struct IFEPortHFRConfig
{
    UINT32  portResourceId;     ///< Identifies port resource
    UINT32  subsamplePattern;   ///< Subsample pattern. Used in HFR mode. It should be
                                ///  consistent with batchSize and CAMIF programming.
    UINT32  subsamplePeriod;    ///< Subsample period. Used in HFR mode. It should be consistent
                                ///  with batchSize and CAMIF programming.
    UINT32  framedropPattern;   ///< Framedrop pattern.
    UINT32  framedropPeriod;    ///< Framedrop period. Must be multiple of subsamplePeriod if in HFR mode.
    UINT32  reserved;           ///< Reserved for alignment
} CAMX_PACKED;

/// @brief HFR configuration
struct IFEResourceHFRConfig
{
    UINT32              numPorts;           ///< Number of Ports to configure for HFR
    UINT32              reserved;           ///< Reserved for alignment
    IFEPortHFRConfig    portHFRConfig[1];   ///< Starting point for HFR Resource config information
} CAMX_PACKED;

static const UINT32 RDIMaxNum = 4;          ///< Max Number of RDIs

/// @brief IFE Clock and settings to configure the IFE core clocks
struct IFEResourceClockConfig
{
    UINT32  usageType;           ///< Single IFE or Dual IFE mode
    UINT32  numRdi;              ///< Number of RDIs - KMD expects this to match RDIMaxNum
    UINT64  leftPixelClockHz;    ///< Pixel clock for "left" IFE. If Single IFE in use, only this value is populated.
    UINT64  rightPixelClockHz;   ///< Pixel clock for "right" IFE. Only valid if dual IFEs are in use.
    UINT64  rdiClockHz[1];       ///< Clock rate for RDI path
} CAMX_PACKED;

/// @brief IFE Bandwidth votes needed by the IFE for the active use case
struct IFEResourceBWVote
{
    UINT32  usageType;           ///< Single IFE or Dual IFE mode
    UINT32  reserved;            ///< Number of RDIs
    UINT64  camnocBWbytes;       ///< Uncompressed BW in bytes required within CAMNOC
    UINT64  externalBWbytes;     ///< BW in bytes required outside of CAMNOC (MNOC etc). Accounts for compression if enabled.
} CAMX_PACKED;

/// @brief IFE Bandwidth votes needed by the IFE for the active use case
struct IFEResourceBWConfig
{
    UINT32             usageType;        ///< Single IFE or Dual IFE mode
    UINT32             numRdi;           ///< Number of RDIs
    IFEResourceBWVote  leftPixelVote;    ///< Bandwidth vote for "left" IFE, valid for single IFE
    IFEResourceBWVote  rightPixelVote;   ///< Bandwidth vote for "right" IFE, valid for dual IFEs
    IFEResourceBWVote  rdiVote[4];       ///< Bandwidth vote for RDI path
} CAMX_PACKED;

CAMX_STATIC_ASSERT_MESSAGE((sizeof(IFEDualConfig) % 8) == 0,          "IFEDualConfig 64b-aligned");
CAMX_STATIC_ASSERT_MESSAGE((sizeof(IFEPortHFRConfig) % 8) == 0,       "IFEPortHFRConfig 64b-aligned");
CAMX_STATIC_ASSERT_MESSAGE((sizeof(IFEResourceHFRConfig) % 8) == 0,   "IFEResourceHFRConfig 64b-aligned");
CAMX_STATIC_ASSERT_MESSAGE((sizeof(IFEResourceClockConfig) % 8) == 0, "IFEResourceClockConfig 64b-aligned");
CAMX_STATIC_ASSERT_MESSAGE((sizeof(IFEResourceBWVote) % 8) == 0,       "IFEResourceBWVote 64b-aligned");
CAMX_STATIC_ASSERT_MESSAGE((sizeof(IFEResourceBWConfig) % 8) == 0,    "IFEResourceBWConfig 64b-aligned");

CAMX_END_PACKED

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Class that implements the IFE node class
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class IFENode final : public Node
{
public:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Create
    ///
    /// @brief  Static method to create IFENode Object.
    ///
    /// @param  pCreateInputData  Node create input data
    /// @param  pCreateOutputData Node create output data
    ///
    /// @return Pointer to the concrete IFENode object
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static IFENode* Create(
        const NodeCreateInputData* pCreateInputData,
        NodeCreateOutputData*      pCreateOutputData);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Destroy
    ///
    /// @brief  This method destroys the derived instance of the interface
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual VOID Destroy();

protected:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ProcessingNodeInitialize
    ///
    /// @brief  Initialize the hwl object
    ///
    /// @param  pCreateInputData  Node create input data
    /// @param  pCreateOutputData Node create output data
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult ProcessingNodeInitialize(
        const NodeCreateInputData* pCreateInputData,
        NodeCreateOutputData*      pCreateOutputData);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ProcessingNodeFinalizeInitialization
    ///
    /// @brief  Method to finalize the initialization of the node in the pipeline
    ///
    /// @param  pFinalizeInitializationData Finalize data
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult ProcessingNodeFinalizeInitialization(
        FinalizeInitializationData* pFinalizeInitializationData);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PostPipelineCreate
    ///
    /// @brief  virtual method to be called at NotifyTopologyCreated time; node should take care of updates and initialize
    ///         blocks that has dependency on other nodes in the topology at this time.
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult PostPipelineCreate();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ProcessingNodeFinalizeInputRequirement
    ///
    /// @brief  Virtual method implemented by IFE node to determine its input buffer requirements based on all the output
    ///         buffer requirements
    ///
    /// @param  pBufferNegotiationData  Negotiation data for all output ports of a node
    ///
    /// @return Success if the negotiation was successful, Failure otherwise
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult ProcessingNodeFinalizeInputRequirement(
        BufferNegotiationData* pBufferNegotiationData);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FinalizeBufferProperties
    ///
    /// @brief  Finalize the buffer properties of each output port
    ///
    /// @param  pBufferNegotiationData Buffer negotiation data
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual VOID FinalizeBufferProperties(
        BufferNegotiationData* pBufferNegotiationData);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ExecuteProcessRequest
    ///
    /// @brief  Pure virtual method to trigger process request for the hwl node object.
    ///
    /// @param  pExecuteProcessRequestData Process request data
    ///
    /// @return CamxResultSuccess if successful and 0 dependencies, dependency information otherwise
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult ExecuteProcessRequest(
        ExecuteProcessRequestData* pExecuteProcessRequestData);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// OnStreamOn
    ///
    /// @brief  Streamon command
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult OnStreamOn();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// OnStreamOff
    ///
    /// @brief  Streamoff command
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult OnStreamOff();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IFENode
    ///
    /// @brief  Constructor
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    IFENode();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ~IFENode
    ///
    /// @brief  Destructor
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual ~IFENode();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CheckToUseHardcodedRegValues
    ///
    /// @brief  Check and [en|dis]able the use of hardcoded register values
    ///
    /// @param  pHwContext Pointer to the ISP HW context
    ///
    /// @return TRUE/FALSE   TRUE -> Enabled, FALSE -> Disabled
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_INLINE BOOL CheckToUseHardcodedRegValues(
        HwContext* pHwContext)
    {
        Titan17xContext* pContext = static_cast<Titan17xContext*>(pHwContext);
        CAMX_ASSERT(NULL != pContext);

        return pContext->GetTitan17xSettingsManager()->GetTitan17xStaticSettings()->IFEUseHardcodedRegisterValues;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CheckToEnableDualIFEStripeInfo
    ///
    /// @brief  Check and [en|dis]able the use of hardcoded register values
    ///
    /// @param  pHwContext Pointer to the ISP HW context
    ///
    /// @return TRUE/FALSE   TRUE -> Enabled, FALSE -> Disabled
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_INLINE BOOL CheckToEnableDualIFEStripeInfo(
        HwContext* pHwContext)
    {
        Titan17xContext* pContext = static_cast<Titan17xContext*>(pHwContext);
        CAMX_ASSERT(NULL != pContext);

        return pContext->GetTitan17xSettingsManager()->GetTitan17xStaticSettings()->enableIFEDualStripeInfo;
    }

private:
    IFENode(const IFENode&) = delete;                 ///< Disallow the copy constructor.
    IFENode& operator=(const IFENode&) = delete;      ///< Disallow assignment operator.

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// AcquireDevice
    ///
    /// @brief  Helper method to acquire IFE device
    ///
    /// @return CamxResultSuccess
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult AcquireDevice();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ReleaseDevice
    ///
    /// @brief  Helper method to release IFE device
    ///
    /// @return CamxResultSuccess
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult ReleaseDevice();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsStatsOutputPort
    ///
    /// @brief  Helper method to determine if the output port is a stats or not.
    ///
    /// @param  outputPortId OutputportId to check
    ///
    /// @return TRUE if the output port is a stats port, FALSE otherwise
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_INLINE BOOL IsStatsOutputPort(
        UINT outputPortId
        ) const
    {
        BOOL isStatsPort = FALSE;

        switch (outputPortId)
        {
            case IFEOutputPortStatsRS:
            case IFEOutputPortStatsCS:
            case IFEOutputPortStatsIHIST:
            case IFEOutputPortStatsBHIST:
            case IFEOutputPortStatsHDRBE:
            case IFEOutputPortStatsHDRBHIST:
            case IFEOutputPortStatsTLBG:
            case IFEOutputPortStatsBF:
            case IFEOutputPortStatsAWBBG:
                isStatsPort = TRUE;
                break;

            default:
                break;
        }

        return isStatsPort;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsDSOutputPort
    ///
    /// @brief  Helper method to determine if the output port is a stats or DS port.
    ///
    /// @param  outputPortId OutputportId to check
    ///
    /// @return TRUE if the output port is a stats port, FALSE otherwise
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_INLINE BOOL IsDSOutputPort(
        UINT outputPortId
        ) const
    {
        BOOL isDSPort = FALSE;

        switch (outputPortId)
        {
            case IFEOutputPortDS4:
            case IFEOutputPortDS16:
                isDSPort = TRUE;
                break;

            default:
                break;
        }

        return isDSPort;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// EnableCSIDCropOverridingForSingleIFE
    ///
    /// @brief  Helper method to determine if CSID crop override mode is enabled
    ///
    /// @return TRUE if the CSID crop override mode is enabled
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_INLINE BOOL EnableCSIDCropOverridingForSingleIFE() const
    {
        BOOL enableCSIDCropOverriding = FALSE;

        if ((m_instanceProperty.IFECSIDWidth > 0) && (m_instanceProperty.IFECSIDHeight> 0))
        {
            enableCSIDCropOverriding = TRUE;
        }

        return enableCSIDCropOverriding;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsPixelOutputPortSourceType
    ///
    /// @brief  Helper method to determine if the output port is a pixel or an undefined port source type
    ///
    /// @param  outputPortId OutputportId to check
    ///
    /// @return TRUE if the output port is a pixel or an undefined port source type
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    BOOL IsPixelOutputPortSourceType(
        UINT outputPortId);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// TranslateCSIDataTypeToCSIDecodeFormat
    ///
    /// @brief  Helper method to map CSI DataType (DT) information to CSI decode format information for ISP.
    ///
    /// @param  CSIDataType the CSI data type
    ///
    /// @return CSID decode format
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    UINT8 TranslateCSIDataTypeToCSIDecodeFormat(
        const UINT8 CSIDataType);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// TranslateBitDepthToCSIDecodeFormat
    ///
    /// @brief  Helper method to map plain bit width to CSI decode format information for ISP.
    ///
    /// @param  bitWidth    the MIPI bit width
    ///
    /// @return CSID decode format
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    UINT8 TranslateBitDepthToCSIDecodeFormat(
        const UINT32 bitWidth);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// TranslateSensorStreamConfigTypeToPortSourceType
    ///
    /// @brief  Helper method to map sensor stream type to port source type ID
    ///
    /// @param  streamType  the sensor stream type to be translated.
    ///
    /// @return port source type ID
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    UINT TranslateSensorStreamConfigTypeToPortSourceType(
        StreamType streamType);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// TranslatePortSourceTypeToSensorStreamConfigType
    ///
    /// @brief  Helper method to map port source type ID to sensor stream type
    ///
    /// @param  portSourceTypeId Port source type to translate
    ///
    /// @return Stream type
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    UINT32 TranslatePortSourceTypeToSensorStreamConfigType(
        UINT portSourceTypeId);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// TranslateColorFilterPatternToISPPattern
    ///
    /// @brief  Helper method to map sensor color filter arrangement value to ISP Bayer pattern
    ///
    /// @param  colorFilterArrangementValue the sensor provided color filter arrangement value
    ///
    /// @return ISP Bayer pattern value
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    UINT32 TranslateColorFilterPatternToISPPattern(
        const enum SensorInfoColorFilterArrangementValues colorFilterArrangementValue);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FindSensorStreamConfigIndex
    ///
    /// @brief  Find the index of the given sensor stream config for the given type
    ///
    /// @param  streamType      the sensor stream type to find
    /// @param  pStreamIndex    the sensor stream index found, or pass NULL if only the index is not needed.
    ///
    /// @return TRUE if the given stream type is found in in the availabe sensor config streams
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    BOOL FindSensorStreamConfigIndex(
        StreamType  streamType,
        UINT*       pStreamIndex);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CheckOutputPortIndexIfUnsupported
    ///
    /// @brief  Check if the given output port index needs to be disabled if the current sensor mode does not support it
    ///
    /// @param  outputPortIndex the given output port index
    ///
    /// @return true of the given output port index needs to be disabled
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    BOOL CheckOutputPortIndexIfUnsupported(
        UINT outputPortIndex);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetRDIOutputPortFormat
    ///
    /// @brief  Set the RDI output based on the port source type.
    ///
    /// @param  pOutputResource     the pointer to the RDI output resource to configure
    /// @param  format              the format from image format type
    /// @param  outputPortId        the given output port Id
    /// @param  portSourceTypeId    the the port source type Id
    ///
    /// @return CamxResultSuccess if successful, otherwise return the failure result
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult SetRDIOutputPortFormat(
        ISPOutResourceInfo* pOutputResource,
        Format              format,
        UINT                outputPortId,
        UINT                portSourceTypeId);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ConfigureIFECapability
    ///
    /// @brief  Set up IFE capability based on IFE revision number
    ///
    /// @return CamxResultSuccess
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult ConfigureIFECapability();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CreateIFEIQModules
    ///
    /// @brief  Create IQ Modules of the IFE Block
    ///
    /// @return CamxResultSuccess
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult CreateIFEIQModules();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CreateIFEStatsModules
    ///
    /// @brief  Create Stats Modules of the IFE Block
    ///
    /// @return CamxResultSuccess
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult CreateIFEStatsModules();


    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CreateIFEHVXModules
    ///
    /// @brief  Create Stats Modules of the IFE Block
    ///
    /// @return CamxResultSuccess
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult CreateIFEHVXModules();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetIFEIQModulesOfType
    ///
    /// @brief  Get IFE IQ module
    ///
    /// @param  moduleType Module type
    ///
    /// @return CamxResultSuccess
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    IFEIQModuleInfo GetIFEIQModulesOfType(
        ISPIQModuleType   moduleType);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PrepareStripingParameters
    ///
    /// @brief  Prepare input parameters for striping lib
    ///
    /// @param  pInputData Pointer to the input data
    ///
    /// @return CamxResultSuccess if successful.
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    CamxResult PrepareStripingParameters(
        ISPInputData* pInputData);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ProgramIQConfig
    ///
    /// @brief  Reprogram the settings for the IQ Modules
    ///
    /// @param  pInputData Pointer to the input data
    ///
    /// @return CamxResult True on successful execution else False on failure
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult ProgramIQConfig(
        ISPInputData* pInputData);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ProgramIQEnable
    ///
    /// @brief  Helper to program enable bits for the IQ Modules
    ///
    /// @param  pInputData Pointer to the input data
    ///
    /// @return CamxResult True on successful execution else False on failure
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult ProgramIQEnable(
        ISPInputData* pInputData);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// DumpTuningMetadata
    ///
    /// @brief  Helper to publish tuning metadata
    ///
    /// @param  pInputData Pointer to the input data
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID DumpTuningMetadata(
        ISPInputData* pInputData);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ProgramIQModuleEnableConfig
    ///
    /// @brief  Reprogram the Module enable settings for the IQ Modules
    ///
    /// @param  pInputData Pointer to the input data
    ///
    /// @return CamxResult True on successful execution else False on failure
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult ProgramIQModuleEnableConfig(
        ISPInputData* pInputData);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ProgramStripeConfig
    ///
    /// @brief  Program output split info for dual IFE stripe
    ///
    /// @return CamxResult True on successful execution else False on failure
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult ProgramStripeConfig();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetStaticMetadata
    ///
    /// @brief  Get all static information from HAL metadata tags for all IFE modules
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID GetStaticMetadata();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetMetadataTags
    ///
    /// @brief  Get all information from HAL metadata tags for all IFE modules
    ///
    /// @param  pModuleInput Pointer to the input data
    ///
    /// @return CamxResultSuccess if successful.
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult GetMetadataTags(
        ISPInputData* pModuleInput);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PrepareBFStatsMetadata
    ///
    /// @brief  Prepare BF stats metadata to be posted to property pool
    ///
    /// @param  pInputData  Pointer to internal ife data
    /// @param  pMetadata   Pointer to metadata to be updated
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID PrepareBFStatsMetadata(
        const ISPInputData* pInputData,
        PropertyISPBFStats* pMetadata);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PrepareHDRBEStatsMetadata
    ///
    /// @brief  Prepare HDR BE stats metadata to be posted to property pool
    ///
    /// @param  pInputData  Pointer to internal ife data
    /// @param  pMetadata   Pointer to metadata to be updated
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID PrepareHDRBEStatsMetadata(
        const ISPInputData*     pInputData,
        PropertyISPHDRBEStats*  pMetadata);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PrepareAWBBGStatsMetadata
    ///
    /// @brief  Prepare AWB BG stats metadata to be posted to property pool
    ///
    /// @param  pInputData  Pointer to internal ife data
    /// @param  pMetadata   Pointer to metadata to be updated
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID PrepareAWBBGStatsMetadata(
        const ISPInputData*     pInputData,
        PropertyISPAWBBGStats*  pMetadata);


    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PrepareCSStatsMetadata
    ///
    /// @brief  Prepare CS stats metadata to be posted to property pool
    ///
    /// @param  pInputData  Pointer to internal ife data
    /// @param  pMetadata   Pointer to metadata to be updated
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID PrepareCSStatsMetadata(
        const ISPInputData* pInputData,
        PropertyISPCSStats* pMetadata);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PrepareRSStatsMetadata
    ///
    /// @brief  Prepare RS stats metadata to be posted to property pool
    ///
    /// @param  pInputData  Pointer to internal ife data
    /// @param  pMetadata   Pointer to metadata to be updated
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID PrepareRSStatsMetadata(
        const ISPInputData* pInputData,
        PropertyISPRSStats* pMetadata);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PrepareIHistStatsMetadata
    ///
    /// @brief  Prepare Ihist stats metadata to be posted to property pool
    ///
    /// @param  pInputData  Pointer to internal ife data
    /// @param  pMetadata   Pointer to metadata to be updated
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID PrepareIHistStatsMetadata(
        const ISPInputData*     pInputData,
        PropertyISPIHistStats*  pMetadata);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PrepareBHistStatsMetadata
    ///
    /// @brief  Prepare Bhist stats metadata to be posted to property pool
    ///
    /// @param  pInputData  Pointer to internal ife data
    /// @param  pMetadata   Pointer to metadata to be updated
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID PrepareBHistStatsMetadata(
        const ISPInputData*     pInputData,
        PropertyISPBHistStats*  pMetadata);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PrepareHDRBHistStatsMetadata
    ///
    /// @brief  Prepare HDR Bhist stats metadata to be posted to property pool
    ///
    /// @param  pInputData  Pointer to internal ife data
    /// @param  pMetadata   Pointer to metadata to be updated
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID PrepareHDRBHistStatsMetadata(
        const ISPInputData*         pInputData,
        PropertyISPHDRBHistStats*   pMetadata);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PrepareTintlessBGStatsMetadata
    ///
    /// @brief  Prepare Tintless BG stats metadata to be posted to property pool
    ///
    /// @param  pInputData  Pointer to internal ife data
    /// @param  pMetadata   Pointer to metadata to be updated
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID PrepareTintlessBGStatsMetadata(
        const ISPInputData*     pInputData,
        PropertyISPTintlessBG*  pMetadata);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PostMetadata
    ///
    /// @brief  Post IFE metadata to main metadata pool
    ///
    /// @param  pInputData Pointer to the input data
    ///
    /// @return CamxResultSuccess if successful.
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult PostMetadata(
        const ISPInputData* pInputData);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PostMetadataRaw
    ///
    /// @brief  Post IFE metadata to main metadata pool
    ///
    /// @return CamxResultSuccess if successful.
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult PostMetadataRaw();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PostMetadataTags
    ///
    /// @brief  Post IFE metadata tags to HAL
    ///
    /// @param  pInputData      Pointer to the input data
    /// @param  ppData          Pointer to data to fill out
    /// @param  pDataCount      Pointer to the data count
    /// @param  index           Pointer to the index into pData array
    ///
    /// @return CamxResultSuccess if successful.
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult PostMetadataTags(
        const ISPInputData* pInputData,
        const VOID**        ppData,
        UINT*               pDataCount,
        UINT                index);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ComputeNeutralPoint
    ///
    /// @brief  Post IFE Sensor Neutral Point to metadata tag to HAL
    ///
    /// @param  pInputData      Pointer to the input data
    /// @param  pNeutralPoint   Pointer to the computed neutral point
    ///
    /// @return CamxResultSuccess if successful.
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult ComputeNeutralPoint(
        const ISPInputData* pInputData,
        Rational*           pNeutralPoint);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CalculateIQCmdSize
    ///
    /// @brief  Calculate Maximum Command Buffer size required for all the available IQ Modules
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID CalculateIQCmdSize();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Cleanup
    ///
    /// @brief  Clean up the allocated IQ modules and Stats Modules
    ///
    /// @return CamxResultSuccess if success
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult Cleanup();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetOEMIQSettings
    ///
    /// @brief  Get IQ Settings configured by OEMs
    ///
    /// @param  ppOEMData   Pointer to the OEM data to be returned
    ///
    /// @return CamxResultSuccess if success
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult GetOEMIQSettings(
        VOID** ppOEMData);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetOEMStatsConfig
    ///
    /// @brief  Returns OEM's custom stats configuration
    ///
    /// @param  pFrameConfig     Pointer to the Frame config data
    ///
    /// @return CamxResultSuccess if success
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult GetOEMStatsConfig(
        ISPStripeConfig* pFrameConfig);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Get3AFrameConfig
    ///
    /// @brief  Returns 3A frame configuration
    ///
    /// @param  pModuleInput     Pointer to the module input
    /// @param  pFrameConfig     Pointer to the Frame config data
    /// @param  requestId        Process Request ID
    ///
    /// @return CamxResultSuccess if success
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult Get3AFrameConfig(
        ISPInputData*    pModuleInput,
        ISPStripeConfig* pFrameConfig,
        UINT64           requestId);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetDependencies
    ///
    /// @brief  Check the availability of the dependence data. Update the data if it is available
    ///
    /// @param  pNodeRequestData        Pointer to the incoming NodeProcessRequestData
    /// @param  hasExplicitDependencies TRUE any explicit dependencies such as 3A stats etc. are required. Will be FALSE
    ///                                 if only PropertyIDISPExecProcDone dependency is set.
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID SetDependencies(
        NodeProcessRequestData* pNodeRequestData,
        BOOL                    hasExplicitDependencies);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// HardcodeSettings
    ///
    /// @brief  Set the hardcode input values until 3A is completly integrated
    ///
    /// @param  pModuleInput Pointer to the IQ module input data
    /// @param  pFrameConfig Pointer to the Frame config data
    /// @param  initalConfig Flag to indicate if the config is during config streams
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID HardcodeSettings(
        ISPInputData*     pModuleInput,
        ISPStripeConfig*  pFrameConfig,
        BOOL              initalConfig);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// HardcodeTintlessSettings
    ///
    /// @brief  Set the hardcode input values to Tintless
    ///
    /// @param  pModuleInput Pointer to the IQ module input data
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID HardcodeTintlessSettings(
        ISPInputData*     pModuleInput);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// DynamicCAMIFCrop
    ///
    /// @brief  Apply CAMIF crop if available from node instance
    ///
    /// @param  pStripeConfig Pointer to the Stripe config data
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID DynamicCAMIFCrop(
        ISPStripeConfig* pStripeConfig);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CreateCmdBuffers
    ///
    /// @brief  Helper method to initialize command manager and to allocate command buffers
    ///
    /// @return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult CreateCmdBuffers();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FetchCmdBuffers
    ///
    /// @brief  Helper method to fetch command buffers for a particular request
    ///
    /// @param  requestId Request number to which command buffer needs to be fetched
    ///
    /// @return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult FetchCmdBuffers(
        UINT64  requestId);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// AddCmdBufferReference
    ///
    /// @brief  Helper method to add command buffer reference to CSL packet
    ///
    /// @param  requestId Request number to which command buffer refrence needs to be added
    /// @param  opcode    CSL opcode init/Update
    ///
    /// @return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult AddCmdBufferReference(
        UINT64              requestId,
        CSLPacketOpcodesIFE opcode);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CommitAndSubmitPacket
    ///
    /// @brief  Helper method to commit DMI and Packet buffers and do CSL submit
    ///
    /// @return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult CommitAndSubmitPacket();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ConfigBufferIO
    ///
    /// @brief  Helper method to pack Buffer IO into packet
    ///
    /// @param  pExecuteProcessRequestData Pointer to fetch Buffer for IO config
    ///
    /// @return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult ConfigBufferIO(
        ExecuteProcessRequestData* pExecuteProcessRequestData);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CheckForRDIOnly
    ///
    /// @brief  Helper method to Check if it is RDI only use case
    ///
    /// @return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult CheckForRDIOnly();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetupDeviceResource
    ///
    /// @brief  Setup List of the Required Resource
    ///
    /// @param  pResource   Pointer to an arry of resource
    ///
    /// @return Number of CSI resource that has been allocated
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    SIZE_T SetupDeviceResource(
        CSLDeviceResource* pResource);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetupChannelResource
    ///
    /// @brief  Setup Channel Resource
    ///
    /// @param  inputPortId          InputPort ID
    /// @param  totalOutputPort      Number of output port in this use case
    /// @param  pOutputPortId        Pointer to the output port id array
    /// @param  pResourceSize        Size of this resource list
    /// @param  portSourceTypeId     Port source type ID if more than one IFE node input port
    ///
    /// @return Pointer to this resource structure
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ISPInResourceInfo* SetupChannelResource(
        UINT        inputPortId,
        UINT        totalOutputPort,
        const UINT* pOutputPortId,
        SIZE_T*     pResourceSize,
        UINT        portSourceTypeId);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// MapPortIdToChannelId
    ///
    /// @brief  Find the OutputChannel based on the port Id
    ///
    /// @param  portId      Port ID defined in the use case xml
    /// @param  pChannelId  Pointer to the physical channel ID
    ///
    /// @return return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult MapPortIdToChannelId(
        UINT    portId,
        UINT32* pChannelId);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetPDAFInformation
    ///
    /// @brief  Get sensor PDAF related data
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID GetPDAFInformation();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetPixelsInSkipPattern
    ///
    /// @brief  Helper method to determine number of pixels in given Skip Pattern
    ///
    /// @param  skipPattern    Skip Pattern
    ///
    /// @return Number of pixels in a skip pattern
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_INLINE UINT32 GetPixelsInSkipPattern(
        UINT16 skipPattern
    ) const
    {
        UINT32 count = 0;

        while (0 < skipPattern)
        {
            count++;
            skipPattern = skipPattern & (skipPattern - 1);
        }

        return count;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetReverseSkipPattern
    ///
    /// @brief  Helper method to get the inverse skip pattern
    ///
    /// @param  skipPattern Skip Pattern
    ///
    /// @return Inverse skip pattern
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_INLINE UINT16 GetReverseSkipPattern(
        UINT16 skipPattern
    ) const
    {
        UINT16 reverseSkipPattern = 0;

        for (UINT index = 0; index < 15; index++)
        {
            reverseSkipPattern |= (skipPattern & 1);
            skipPattern         = skipPattern >> 1;
            reverseSkipPattern  = reverseSkipPattern << 1;
        }
        reverseSkipPattern |= (skipPattern & 1);
        return reverseSkipPattern;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PreparePDAFInformation
    ///
    /// @brief  PreparePDAFInformation
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID PreparePDAFInformation();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ExtractCAMIFDecimatedPattern
    ///
    /// @brief  Extracts the PDAF information pattern from CAMIF subsample
    ///
    /// @param  horizontalOffset Pdaf pixels horizontal offset
    /// @param  verticalOffset   Pdaf pixels vertical offset
    /// @param  pBlockPattern    Pointer to PDAF block pattern data
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID ExtractCAMIFDecimatedPattern(
        UINT32             horizontalOffset,
        UINT32             verticalOffset,
        PDLibBlockPattern* pBlockPattern);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// InitializeOutputPathImageInfo
    ///
    /// @brief  Update ISP input data from the port
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID InitializeOutputPathImageInfo();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsSensorModeFormatBayer
    ///
    /// @brief  Indicate if the given Pixel format is a Bayer type or not.
    ///
    /// @param  format  PixelFormat format
    ///
    /// @return TRUE if the PixelFormat is a Bayer type
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    BOOL IsSensorModeFormatBayer(
        PixelFormat format) const;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsSensorModeFormatMono
    ///
    /// @brief  Indicate if the given Pixel format is a Mono type or not.
    ///
    /// @param  format  PixelFormat format
    ///
    /// @return TRUE if the PixelFormat is a Mono type
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    BOOL IsSensorModeFormatMono(
        PixelFormat format) const;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsSensorModeFormatYUV
    ///
    /// @brief  Indicate if the given Pixel format is a YUV type or not.
    ///
    /// @param  format  PixelFormat format
    ///
    /// @return TRUE if the PixelFormat is a YUV type
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    BOOL IsSensorModeFormatYUV(
        PixelFormat format) const;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsTPGMode
    ///
    /// @brief  Indicate if current mode is TPG or not
    ///
    /// @return TRUE if TPG is enabled
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    BOOL IsTPGMode();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// HardcodeSettingsSetDefaultBFFilterInputConfig
    ///
    /// @brief  Hardcode BF settings with default input filter configuration
    ///
    /// @param  pAFConfigOutput  Pointer to the AF configuration parameter to fill
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID HardcodeSettingsSetDefaultBFFilterInputConfig(
        AFStatsControl* pAFConfigOutput);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// HardcodeSettingsSetDefaultBFROIInputConfig
    ///
    /// @brief  Hardcode BF settings with default region of interest configuration
    ///
    /// @param  pAFConfigOutput Pointer to the AF configuration parameter to fill
    /// @param  CAMIFWidth      The current CAMIF width
    /// @param  CAMIFHeight     The current CAMIF height
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID HardcodeSettingsSetDefaultBFROIInputConfig(
        AFStatsControl* pAFConfigOutput,
        UINT32          CAMIFWidth,
        UINT32          CAMIFHeight);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ReadDefaultStatsConfig
    ///
    /// @brief  Read the default configuration.
    ///
    ///
    /// @param  pModuleInput Pointer to the IQ module input data
    ///
    /// @return return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult ReadDefaultStatsConfig(
        ISPInputData* pModuleInput);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// HardcodeSettingsBFStats
    ///
    /// @brief  Set the hardcode input values for BF stats
    ///
    /// @param  pStripeConfig    The pointer to the frameConfig
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID HardcodeSettingsBFStats(
        ISPStripeConfig* pStripeConfig);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetupHFRInitialConfig
    ///
    /// @brief  Setup HFR initial configuration in Generic Blob Command Buffer
    ///
    /// @return CamxResult True on successful execution else False on failure
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult SetupHFRInitialConfig();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CalculatePixelClockRate
    ///
    /// @brief  Calculates IFE clock rate for the active sensor configuration based on the pixel path's needs.
    ///         Does not account for the override ifeClockFrequencyMHz.
    ///
    /// @param  inputWidth   input width of the data processed by the IFE
    ///
    /// @return Clock rate in Hz required for inputWidth
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    UINT64 CalculatePixelClockRate(
        UINT32  inputWidth);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetPixelClockRate
    ///
    /// @brief  Get IFE clock rate for the active sensor configuration based on the pixel path's needs.
    ///         The override ifeClockFrequencyMHz is also accounted for, and the pPixClockHz value may not be optimal value
    ///         if the override is enabled.
    ///
    /// @param  inputWidth   input width of the data processed by the IFE
    /// @param  pPixClockHz  Clock rate in Hz required for inputWidth
    ///
    /// @return return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult GetPixelClockRate(
        UINT32  inputWidth,
        UINT64* pPixClockHz);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CalculateRDIClockRate
    ///
    /// @brief  Calculates IFE clock rate for the active sensor configuration for the RDI path
    ///
    /// @return clock rate needed
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    UINT64 CalculateRDIClockRate();


    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CalculateSensorLineLength
    ///
    /// @brief  Calculates IFE clock rate for the active sensor configuration for the RDI path
    ///
    /// @param  ifeClockRate   IFE clock rate to use
    ///
    /// @return Line length in micro seconds
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    FLOAT CalculateSensorLineLength(
        UINT64 ifeClockRate);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CalculateBandwidth
    ///
    /// @brief  Calculates the BW required to operate the IFE for the current use case.
    ///         Takes overrides ifeCamnocBandwidthMBytes and ifeExternalBandwidthMBytes into consideration.
    ///
    /// @param  pExecuteProcessRequestData  Pointer to EPR data
    /// @param  pBwResourceConfig           Contains both Uncompressed BW inside camnoc and Compressed BW outside camnoc,
    ///                                     used to config MNOC and the rest of the path to DDR
    /// @param  requestId                   RequestId for which BW config is being setup
    ///
    /// @return return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult CalculateBandwidth(
        ExecuteProcessRequestData* pExecuteProcessRequestData,
        IFEResourceBWConfig*       pBwResourceConfig,
        UINT64                     requestId);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetupResourceClockConfig
    ///
    /// @brief  Setup Clock configuration required for the use case being activated
    ///
    /// @return CamxResult True on successful execution else False on failure
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult SetupResourceClockConfig();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetupResourceBWConfig
    ///
    /// @brief  Setup Bandwidth configuration required for the use case being activated
    ///
    /// @param  pExecuteProcessRequestData  Pointer to EPR data
    /// @param  requestId                   RequestId for which BW config is being setup
    ///
    /// @return CamxResult True on successful execution else False on failure
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult SetupResourceBWConfig(
        ExecuteProcessRequestData* pExecuteProcessRequestData,
        UINT64                     requestId);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetStripeConfigIndex
    ///
    /// @brief  Helper to calculate the index to the stripe config array
    ///
    /// @param  stripe      Stripe index (0 or 1)
    /// @param  maxPorts    Max number of ports in this stripe configuration
    /// @param  portIndex   Port index
    /// @param  plane       Plane index
    ///
    /// @return Index into stripe array
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_INLINE UINT32 GetStripeConfigIndex(
        UINT32 stripe,
        UINT32 maxPorts,
        UINT32 portIndex,
        UINT32 plane) const
    {
        return (stripe * maxPorts * CSLMaxNumPlanes) + (portIndex * CSLMaxNumPlanes) + plane;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// UpdateIQStateConfiguration
    ///
    /// @brief  Update stripe specific configuration to ISP input configuration
    ///
    /// @param  pFrameConfig    The pointer to the frameConfig
    /// @param  pStripeConfig   Structure holding stripe specific configuration
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID UpdateIQStateConfiguration(
        ISPStripeConfig* pFrameConfig,
        ISPStripeConfig* pStripeConfig);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// InitialSetupandConfig
    ///
    /// @brief  Update initial config with respect to clock, HFR, BW
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult InitialSetupandConfig();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetupHVXInitialConfig
    ///
    /// @brief  Setup HVX initial configuration
    ///
    /// @param  pInputData    The pointer to the Input data
    ///
    /// @return CamxResult True on successful execution else False on failure
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult SetupHVXInitialConfig(
        ISPInputData* pInputData);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsFastAECEnabled
    ///
    /// @brief  Check if Fast AEC is enabled
    ///
    /// @return TRUE if Fast AEC is enabled
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    BOOL IsFastAECEnabled();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PublishIFEInputToUsecasePool
    ///
    /// @brief  Publish IFE input usecase pool
    ///
    /// @param  pIFEResolution    The pointer to the Input Resolution
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID PublishIFEInputToUsecasePool(
        IFEInputResolution* pIFEResolution);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CanSkipAlgoProcessing
    ///
    /// @brief  Decides whether we can skip tintless algo processing for the current frame based on skip factor
    ///
    /// @param  requestId current request id
    ///
    /// @return TRUE if we can skip otherwise FALSE
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    BOOL CanSkipAlgoProcessing(
        UINT64 requestId
    )const;

    static const UINT8 MaxIFEOutputPorts = 18;                     ///< Max output ports
    static const UINT8 MaxIFEInputPorts  = 8;                      ///< Max input ports
    static const UINT8 MaxIFEIQModule    = 40;                     ///< Max Number of IQ Modules
    static const UINT8 MaxIFEStatsModule = 10;                     ///< Max Number of Stats Modules
    static const UINT8 MaxIFEResource    = 16;                     ///< Max Number of the IFE Resource Sent to CSI

    CmdBufferManager*        m_pIQPacketManager;                   ///< IQ Packet buffer manager
    CmdBufferManager*        m_pIQMainCmdBufferManager;            ///< Cmd buffer manager for the top-level command buffer
    CmdBufferManager*        m_pIQLeftCmdBufferManager;            ///< Cmd buffer manager for the left IFE (dual IFE)
    CmdBufferManager*        m_pIQRightCmdBufferManager;           ///< Cmd buffer manager for the right IFE (dual IFE)
    CmdBufferManager*        m_pDualIFEConfigCmdBufferManager;     ///< Cmd buffer manager for dual-IFE-specific config data
    CmdBufferManager*        m_p32bitDMIBufferManager;             ///< Buffer Manager for 32bit DMI data
    CmdBufferManager*        m_p64bitDMIBufferManager;             ///< Buffer Manager for 64bit DMI data
    CmdBufferManager*        m_pGenericBlobBufferManager;          ///< Buffer Manager for Generic Blob data

    Packet*                  m_pIQPacket;                          ///< CSL packet
    CmdBuffer*               m_p64bitDMIBuffer;                    ///< 64 bit DMI Buffer
    CmdBuffer*               m_p32bitDMIBuffer;                    ///< 32 bit DMI Buffer
    UINT32*                  m_p64bitDMIBufferAddr;                ///< 64 bit DMI buffer where IQ modules could write LUT
    UINT32*                  m_p32bitDMIBufferAddr;                ///< 32 bit DMI buffer where IQ modules could write LUT

    CSLDeviceHandle          m_hDevice;                             ///< IFE device handle
    ISPIQModule*             m_pIFEIQModule[MaxIFEIQModule];        ///< List of IQ Modules
    ISPIQModule*             m_pIFEHVXModule;                       ///< HVX IQ Modules
    ISPStatsModule*          m_pIFEStatsModule[MaxIFEStatsModule];  ///< List of Stats Modules
    const SensorMode*        m_pSensorModeData;                     ///< Sensor mode related data for the current mode
    const SensorMode*        m_pSensorModeRes0Data;                 ///< Sensor mode related data for FULL SIZE
    const EEPROMOTPData*     m_pOTPData;                            ///< OTP Data read from EEPROM to be used for calibration
    SensorMode               m_testGenModeData;                     ///< TPG mode related data
    IFEInputResolution       m_IFEinputResolution;                  ///< IFE Input resolution
    CSLVersion               m_version;                             ///< IFE Hardware Revision
    IFECapabilityInfo        m_capability;                          ///< IFE Capability Configuration
    UINT                     m_numIFEIQModule;                      ///< Number of IFE IQ Modules
    UINT                     m_totalIQCmdSizeDWord;                 ///< Total Size of IQ Cmd List, in dword
    UINT                     m_total32bitDMISizeDWord;              ///< Total Size of 32 bit DMI buffer, in dword
    UINT                     m_total64bitDMISizeDWord;              ///< Total Size of 64 bit DMI buffer, in dword
    UINT                     m_genericBlobCmdBufferSizeBytes;       ///< Total Size of Generic Blob buffer, in bytes
    UINT                     m_numIFEStatsModule;                   ///< Number of IFE Stats Modules
    IFEPipelineData          m_pipelineData;                        ///< Common Data for the IFE Pipeline
    IFEModuleMode            m_mode;                                ///< Dual or single IFE mode
    DualIFESplitParams       m_dualIFESplitParams;                  ///< Dual IFE split params
    UINT                     m_usecaseNumBatchedFrames;             ///< Number of framework frames batched together if
                                                                    ///  batching is enabled. By default is 1
    UINT32                  m_sensorActiveArrayWidth;               ///< Sensor active array width
    UINT32                  m_sensorActiveArrayHeight;              ///< Sensor active array width
    ISPHALConfigureData     m_ISPInputHALData;                      ///< Cached HAL/App data
    ISPSensorConfigureData  m_ISPInputSensorData;                   ///< Cached sensor module data for ISP input
    ISPHALTagsData          m_HALTagsData;                          ///< Keep all input coming from tags
    IFEHVXInfo              m_HVXInputData;                         ///< HVX input info
    IFEPDAFInfo             m_PDAFInfo;                             ///<  PDAF Information

    IFEOutputPath            m_IFEOutputPathInfo[IFEOutputPortStatsAWBBG + 1]; ///< output paths enabled based on output ports
    BOOL                     m_RDIOnlyUseCase;                                 ///< variable to track RDI only use case
    BOOL                     m_hasStatsNode;                                   ///< variable to track stats node availablilty
    BOOL                     m_enableHardcodedConfig;                          ///< variable to track hardcoded config
    BOOL                     m_useStatsAlgoConfig;                             ///< track if stats algorithm should be used
    BOOL                     m_OEMStatsConfig;                                 ///< Variable to track OEM controlled stats
    BOOL                     m_OEMIQSettingEnable;                             ///< indicator for OEM IQ Setting Mode
    UINT8                    m_CSIDecodeBitWidth;                              ///< Cached CSI decode bit width
    BOOL                     m_currentSensorModeSupportPDAF;                   ///< Current sensor mode has PDAF stream or not
    BOOL                     m_currentSensorModeSupportHDR;                    ///< Current sensor mode has HDR stream or not
    BOOL                     m_currentSensorModeSupportMeta;                   ///< Current sensor mode has Meta stream or not
    UINT                     m_totalInputPorts;                                ///< Total number of input ports
    UINT                     m_disabledOutputPorts;                            ///< Number of disabled output ports
    BOOL                     m_isDisabledOutputPort[MaxIFEOutputPorts];        ///< List of disabed output ports check values
    UINT8                    m_PDAFCSIDecodeFormat;                            ///< Cached PDAF stream CSI decode format
    UINT8                    m_metaCSIDecodeFormat;                            ///< Cached Meta stream CSI decode format
    BOOL                     m_isFastAECEnabled;                               ///< Flag to indicate whether Fast AEC
                                                                               ///  is enabled or not
    UINT                     m_IFECmdBlobCount;                                ///< Number of blob cmd buffers in circulation

    const SensorModuleStaticCaps*   m_pSensorCaps;                             ///< Cached pointer to the sensor capability

    ChiTuningModeParameter  m_tuningData;                           ///< Cached tuning mode selector data, to help optimize
                                                                    ///  tuning data (tree) search in the IQ modules

    // Below fields are used to support dual IFE mode without affecting IQ modules. Depending on the IFE mode, IQ modules
    // will access pointer to the appropriate data below. IFE node sets the pointer to the right value and IQ modules just
    // work as if they always write to a single ISP.
    IFEStripingInput*       m_pStripingInput;                       ///< Striping library input
    IFEPassOutput*          m_pPassOut;                             ///< Striping library's output
    ISPInternalData         m_ISPFramelevelData;                    ///< Frame-level data (used for striping)
    ISPStripeConfig         m_stripeConfigs[2];                     ///< ISP input configuration per stripe
    ISPInternalData         m_ISPData[3];                           ///< Data Calculated by IQ Modules (common, left and right)
    ISPFrameInternalData    m_ISPFrameData;                         ///< Frame-level ISP internal data
    CmdBuffer*              m_pCommonCmdBuffer;                     ///< Pointer to the Command Buffer common to left/right IFEs
    CmdBuffer*              m_pLeftCmdBuffer;                       ///< Pointer to the command buffer specific to the left IFE
    CmdBuffer*              m_pRightCmdBuffer;                      ///< Pointer to the command buffer specific to the right IFE
    CmdBuffer*              m_pDualIFEConfigCmdBuffer;              ///< Pointer to the command buffer containing
                                                                    ///  dual-IFE-specific configuration data
    CmdBuffer*              m_pGenericBlobCmdBuffer;                ///< Pointer to Generic Blob Command Buffer

    IQLibInitialData        m_libInitialData;                       ///< IQ Library initial data
    DebugDataWriter*        m_pDebugDataWriter;                     ///< Pointer to the debug data pointer
    IFETuningMetadata*      m_pTuningMetadata;                      ///< Metadata for tuning support
    BOOL                    m_isMasterCamera;                       ///< Camera master or not

    // Stats metadata field
    PropertyISPBFStats          m_BFStatsMetadata;                   ///< BF stats metadata to be updated and used by parser
    PropertyISPHDRBEStats       m_HDRBEStatsMetadata;                ///< HDR BE stats metadata to be updated and used by parser
    PropertyISPBHistStats       m_bhistStatsMetadata;                ///< BHist stats config
    PropertyISPAWBBGStats       m_AWBBGStatsMetadata;                ///< AWBBG stats metadata to be updated and used by parser
    PropertyISPRSStats          m_RSStatsMetadata;                   ///< RS stats metadata to be updated and used by parser
    PropertyISPCSStats          m_CSStatsMetadata;                   ///< CS stats metadata to be updated and used by parser
    PropertyISPHDRBHistStats    m_HDRBHistStatsMetadata;             ///< HDRBhist stats metadata to be updated
    PropertyISPTintlessBG       m_tintlessBGStatsMetadata;           ///< Tintless BG stats config
    PropertyISPIHistStats       m_IHistStatsMetadata;                ///< IHist stats metadata
    ISPStripeConfig             m_frameConfig;                       ///< FrameLevel config
    BOOL                        m_disableManual3ACCM;                ///< Override to disable manual 3A CCM
    BOOL                        m_initialConfigPending;              ///< Flag to track initial config
    UINT32                      m_resourcePolicy;                    ///< Prefered resource vs power trade-off
    IFEInstanceProperty         m_instanceProperty;                  ///< IFE Node Instance Property
    SIZE_T                      m_resourceBwConfigSize;              ///< Resource Bw config structure size
    IFEResourceBWConfig*        m_pBwResourceConfig;                 ///< Resource BW calculated values
    UINT                        m_highInitialBWCnt;                  ///< Counter for multiplying bw for initial frames
    FLOAT                       m_sensorLineTimeMSecs[2];            ///< Sensor line IFE sees including H blanking
    AFStatsControl              m_previousAFstatsControl;            ///< previous AF stats control
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Class that implements the Dual IFE utils class
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class DualIFEUtils
{
public:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// EvaluateDualIFEMode
    ///
    /// @brief  Static method to evaluate whethere IFE node should run in dual mode or not
    ///
    /// @param  pISPInputdata   ISP configuration to be used to read frame-level settings
    ///
    /// @return DualIFENormal if IFE node should run in dual IFE mode; SingleIFENormal otherwise
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static IFEModuleMode EvaluateDualIFEMode(
        ISPInputData* pISPInputdata);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FillCfgFromOneStripe
    ///
    /// @brief  Static method to fetch configurations of one stripe from striping output
    ///
    /// @param  pISPInputdata ISP configuration to be used to read frame-level settings
    /// @param  pStripeOut    Pointer to striping lib output
    /// @param  pStripeConfig Pointer to stripe config
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static void FillCfgFromOneStripe(
        ISPInputData*       pISPInputdata,
        IFEStripeOutput*    pStripeOut,
        ISPStripeConfig*    pStripeConfig);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FetchCfgWithStripeOutput
    ///
    /// @brief  Static method to fetch configurations from striping output
    ///
    /// @param  pISPInputdata Pointer to ISP configuration to be used to read frame-level settings
    /// @param  pPassOut      Pointer to striping lib output
    /// @param  pStripeConfig Pointer to stripe config
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static void FetchCfgWithStripeOutput(
        ISPInputData*       pISPInputdata,
        IFEPassOutput*      pPassOut,
        ISPStripeConfig*    pStripeConfig);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ComputeSplitParams
    ///
    /// @brief  Static method to compute dual IFE split parameters
    ///
    /// @param  pISPInputdata   ISP configuration to be used to read frame-level settings, and to which the results will be
    ///                         written.
    /// @param  pSplitParams    Pointer to split parameters structure to be updated
    ///
    /// @return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CamxResult ComputeSplitParams(
        ISPInputData*       pISPInputdata,
        DualIFESplitParams* pSplitParams);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ReleaseDualIfePassResult
    ///
    /// @brief  Static method to release Dual Ife stripping lib output
    ///
    /// @param  pPassOut        Stripe specific parameters used by striping library
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static void ReleaseDualIfePassResult(
        IFEPassOutput* pPassOut);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PrintDualIfeInput
    ///
    /// @brief  Print Log for Dual IFE Stripe library input configurations
    ///
    /// @param  pStripingInput  Stripe input configurations
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static void PrintDualIfeInput(
        const stripingInput_titanIFE* pStripingInput);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PrintDualIfeOutput
    ///
    /// @brief  Print Log for Dual IFE Stripe library input configurations
    ///
    /// @param  pStripeOut    Pointer to striping lib output
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static void PrintDualIfeOutput(
        const IFEStripeOutput* pStripeOut);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PrintDualIfeFrame
    ///
    /// @brief  Print Log for Dual IFE Stripe library input configurations
    ///
    /// @param  pPassOut        Stripe specific parameters used by striping library
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static void PrintDualIfeFrame(
        const IFEPassOutput* pPassOut);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// UpdateDualIFEConfig
    ///
    /// @brief  Static method to update ISP configuration based on the current dual IFE split params
    ///
    /// @param  pISPInputdata   ISP configuration to be used to read frame-level settings
    /// @param  PDAFInfo        PDAF Pixel information
    /// @param  pStripeConfig   ISP stripe-level configuration to to be written to
    /// @param  pSplitParams    Split parameters
    /// @param  pPassOut        Stripe specific parameters used by striping library
    ///
    /// @return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CamxResult UpdateDualIFEConfig(
        ISPInputData*       pISPInputdata,
        const IFEPDAFInfo   PDAFInfo,
        ISPStripeConfig*    pStripeConfig,
        DualIFESplitParams* pSplitParams,
        IFEPassOutput*      pPassOut);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetDefaultDualIFEStatsConfig
    ///
    /// @brief  Static method to calculate default Stats configuration for Dual IFE
    ///
    /// @param  pISPInputdata   ISP configuration to be used to read frame-level settings
    /// @param  pStripeConfig   ISP stripe-level configuration to to be written to
    /// @param  pSplitParams    Split parameters
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static VOID GetDefaultDualIFEStatsConfig(
        ISPInputData*       pISPInputdata,
        ISPStripeConfig*    pStripeConfig,
        DualIFESplitParams* pSplitParams);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// UpdateStripingInput
    ///
    /// @brief  Static method to update striping lib input params
    ///
    /// @param  pISPInputdata   ISP configuration to be used to read frame-level settings, and to which the results will be
    ///                         written.
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static VOID UpdateStripingInput(
        ISPInputData* pISPInputdata);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// TranslateOutputFormatToStripingLib
    ///
    /// @brief  Static method to translate CamX output image format to striping lib's format
    ///
    /// @param  srcFormat   Camx::Format
    ///
    /// @return Striping lib's format enum
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static int16_t TranslateOutputFormatToStripingLib(
        Format srcFormat);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// TranslateInputFormatToStripingLib
    ///
    /// @brief  Static method to translate CamX input image format to striping lib's format
    ///
    /// @param  srcFormat       Camx::Format
    /// @param  CSIDBitWidth    Sensor bitwidth
    ///
    /// @return Striping lib's format enum
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static int16_t TranslateInputFormatToStripingLib(
        PixelFormat srcFormat,
        UINT32      CSIDBitWidth);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetPixelsInSkipPattern
    ///
    /// @brief  Helper method to determine number of pixels in given Skip Pattern
    ///
    /// @param  skipPattern    Skip Pattern
    ///
    /// @return Number of pixels in a skip pattern
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT32 GetPixelsInSkipPattern(
        UINT16 skipPattern)
    {
        UINT32 count = 0;

        while (0 < skipPattern)
        {
            count++;
            skipPattern = skipPattern & (skipPattern - 1);
        }

        return count;
    }
};

CAMX_NAMESPACE_END

#endif // CAMXIFENODE_H
